package com.zf.jetcache.service;

import com.alicp.jetcache.CacheManager;
import com.alicp.jetcache.anno.CacheInvalidate;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CacheUpdate;
import com.alicp.jetcache.anno.Cached;
import com.zf.jetcache.entity.Product;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 注解详解：https://github.com/alibaba/jetcache/blob/master/docs/CN/MethodCache.md
 */
@Service
@Slf4j
public class ProductService {

    // 缓存的名称，缓存名称对应的缓存如果不存在会自动创建缓存
    public static final String CACHE_NAME = "productCache:";

    public static final String DEFAULT_AREA = "default";
    public static final String OTHER_AREA = "other";

    /**
     * 可以注入 CacheManager 手动操作缓存，在jetcache 2.7 版本CreateCache注解已经废弃，可以使用CacheManager.getOrCreateCache(QuickConfig) 自定义缓存
     * 详见：https://github.com/alibaba/jetcache/blob/master/docs/CN/CreateCache.md
     */
    @Autowired
    private CacheManager cacheManager;


    /**
     * Cached注解，如果 key 存在就查询缓存，不执行方法，否则执行方法把结果写入缓存
     * area 指定使用的area, 默认是default
     * name 缓存的名称，如果对应名称的缓存不存在，则会自动创建
     * key 缓存对象的唯一标识, 在本地缓存中就是key指定的值，在写入远程缓存 或者 从远程缓存中读取时 会自动按照配置添加指定的前缀，详细说明见配置文件，支持SpEL表达式
     * cacheType 缓存到 本地、远程、同时本地及远程，需要在本地或者远程添加对应名称的 area, 否则使用时会报错
     * cacheNullValue 是否缓存 null
     * expire 远程和本地缓存的过期时间，默认时间单位是秒，60s后删除本地和远程缓存
     */
    @Cached(area = OTHER_AREA, name = CACHE_NAME, key = "#id", cacheType = CacheType.BOTH, cacheNullValue = true, expire = 60)
    public Product getById(Long id) {
        log.info("进入了get方法，数据：{}", id);
        return null;
    }

    /**
     * CacheUpdate用于更新缓存，更新后会重置 expire 过期时间，相当于先删除在插入
     * name 缓存的名称，如果对应名称的缓存不存在，则会自动创建
     * value 指定被缓存的对象, 用于更新缓存 支持SpEL表达式
     */
    @CacheUpdate(area = OTHER_AREA, name = CACHE_NAME, key = "#product.id", value = "#result")
    public Product save(Product product) {
        log.info("进入了save方法，数据：{}", product);
        return product;
    }


    @CacheUpdate(area = OTHER_AREA, name = CACHE_NAME, key = "#product.id", value = "#result")
    public Product update(Product product) {
        log.info("进入了update方法，数据：{}", product);
        return product;
    }
    /**
     * CacheInvalidate 用于删除缓存
     * name 缓存的名称，如果对应名称的缓存不存在，则会自动创建
     */
    @CacheInvalidate(area = OTHER_AREA, name = CACHE_NAME, key = "#id")
    public void delete(Long id) {
        log.info("进入了delete方法，数据：{}", id);
    }

    /**
     * CacheInvalidate . 批量删除
     * multi 为true 标识 批量删除 Iterator 中的每个 key
     */
    @CacheInvalidate(area = OTHER_AREA, name = CACHE_NAME, key = "#idList", multi = true)
    public void deleteAll(List<Long> idList) {
        log.info("进入了deleteAll方法，数据：{}", idList);
    }
}
